package dto

import (
	"crypto/sha256"
	"errors"
	"fmt"
	"k9-panel/app/model"
	"strings"
)

type ProjectListParam struct {
	//AccountId uint `form:"account_id" binding:"required"`
	Account *model.Account
}
type ProjectBaseConfigInfo struct {
	Project              *ProjectData `json:"project"`
	DependencyProjectIds []*uint      `json:"dependencyProjectIds"`
	Content              string       `json:"content"`
}
type ProjectData struct {
	Id   uint   `json:"id"`
	Name string `json:"name"`
}

type DerivedAddParam struct {
	ProjectId            uint   `form:"projectId"`
	EnvironmentId        uint   `form:"environmentId"`
	DependencyProjectIds []uint `form:"dependencyProjectIds"`
	Content              string `form:"content"`
}

type ConfigEnvItem struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	Sort  int    `json:"sort"`
}
type ConfigEnv struct {
	Comment string           `json:"comment"`
	Items   []*ConfigEnvItem `json:"items"`
}

func (receiver *ConfigEnv) ToString() (string, error) {
	var (
		configText strings.Builder
	)
	if receiver.Items != nil && len(receiver.Items) > 0 {
		configText.WriteString("##" + receiver.Comment + "\n")
		for _, item := range receiver.Items {
			if strings.HasPrefix(item.Key, "##") || strings.HasPrefix(item.Key, "#") {
				if item.Value == "1" {
					configText.WriteString(fmt.Sprintf("%s \n", item.Key))
				} else {
					configText.WriteString(fmt.Sprintf("%s=%s\n", item.Key, item.Value))
				}
			} else {

				configText.WriteString(fmt.Sprintf("%s=%s\n", item.Key, item.Value))
			}
		}
		configText.WriteString("\n\n")

	}

	return configText.String(), nil
}

var ErrRepeat = errors.New("repeat config")

func (receiver *ConfigEnv) ToMap() (map[string]interface{}, error) {
	var (
		configText map[string]interface{}
	)
	configText = make(map[string]interface{})
	for _, item := range receiver.Items {
		configText[item.Key] = item.Value
	}
	if len(configText) != len(receiver.Items) {
		return nil, ErrRepeat
	}
	return configText, nil
}

func (receiver *ConfigEnv) Merge(env *ConfigEnv) (*ConfigEnv, error) {
	//检测 key是否重复，
	//写入一个comment map
	//返回ConfigEnv

	meMap, err := receiver.ToMap()
	if err != nil {
		return receiver, err
	}
	if env.Items == nil || len(env.Items) == 0 {
		return receiver, err
	}
	receiver.Items = append(receiver.Items, &ConfigEnvItem{Key: "##" + env.Comment, Value: "1"})

	for _, item := range env.Items {
		if _, ok := meMap[item.Key]; !ok {
			receiver.Items = append(receiver.Items, &ConfigEnvItem{Key: item.Key, Value: item.Value})
		}
	}

	return receiver, nil
}

func (receiver *ConfigEnv) MergeBeforeMe(env *ConfigEnv) (*ConfigEnv, error) {
	//检测 key是否重复，
	//写入一个comment map
	//返回ConfigEnv

	meMap, err := receiver.ToMap()
	if err != nil {
		return receiver, err
	}
	if env.Items == nil || len(env.Items) == 0 {
		return receiver, err
	}
	receiver.Items = append([]*ConfigEnvItem{{Key: "##" + env.Comment + " End", Value: "1"}}, receiver.Items...)

	for _, item := range env.Items {
		if _, ok := meMap[item.Key]; !ok {
			receiver.Items = append([]*ConfigEnvItem{{Key: item.Key, Value: item.Value}}, receiver.Items...)
		}
	}
	receiver.Items = append([]*ConfigEnvItem{{Key: "##" + env.Comment + " Start ", Value: "1"}}, receiver.Items...)

	return receiver, nil
}

type QueryListHistory struct {
	ProjectId     uint `form:"projectId"`
	EnvironmentId uint `form:"environmentId"`
	PageSize      int  `form:"pageSize"`
	PageIndex     int  `form:"page"`
}
type HistoryConfigPublishParam struct {
	ProjectId     uint   `form:"projectId"`
	EnvironmentId uint   `form:"environmentId"`
	Content       string `form:"content"`
	Memo          string `form:"memo"`
}
type AccountCreateParam struct {
	Username    string `form:"username"`
	Password    string `form:"password"`
	OldPassword string `form:"password"`
}
type AccountDeleteParam struct {
	Username string `form:"username"`
}
type AccountQueryParam struct {
	Username string `form:"username"`
	Password string `form:"password"`
}
type RspListHistory struct {
	Items []*model.HistoryConfig
	Total int64
}

type Token struct {
	Value string `json:"token"`
}

func (receiver *Token) Hash(salt string) string {
	hash := sha256.New()
	hash.Write([]byte(fmt.Sprintf("%s%s", salt, receiver.Value)))
	return string(fmt.Sprintf("%s.%x", salt, hash.Sum(nil)))
}
func (receiver *Token) Same(token string) (bool, error) {
	tokenInfo := strings.Split(token, ".")
	if len(tokenInfo) != 2 {
		return false, errors.New("invalid token")
	}
	return receiver.Hash(tokenInfo[0]) == token, nil
}

const IdentityKey = "id"

// User demo
type User struct {
	Username string `json:"username"`
	Super    bool   `json:"super"`
	ID       uint   `json:"id"`
}

func (receiver User) ToAccount() *model.Account {
	return &model.Account{
		Username: receiver.Username,
		Super:    receiver.Super,
		Model: model.Model{
			ID: receiver.ID,
		},
	}
}
